/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package com.sarco.bwi.lib;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author iktsup
 */
public class Blender {
    public static String PARAM_BG           = "-b";
    public static String PARAM_START_FRAME  = "-s";
    public static String PARAM_END_FRAME    = "-e";
    public static String PARAM_PATH         = "-o";
    public static String PARAM_FORMAT       = "-F";
    public static String PARAM_ADD_FILE_EXT = "-x";
    public static String PARAM_ANIMATION    = "-a";
    public static String PARAM_DEBUG        = "-d";

    public static String MSG_APPEND_FRAME   = "Append frame ";
    public static String MSG_TIME           = "Time: ";

    public static String SPACE = " ";

    public static String DEFAULT_PATH = "//render_#";

    private String blenderPath;
    private String file;
    private int startFrame;
    private int endFrame;
    private String path;
    private String format;
    private int addFileExt;
    private Socket client;

    private String command;

    public Blender(String blenderPath, String file, int startFrame,
            int endFrame, String path, String format, int addFileExt) {
         this.blenderPath = blenderPath;
         this.file = file;
         this.startFrame = startFrame;
         this.endFrame = endFrame;
         this.path = path;
         this.format = format;
         this.addFileExt = addFileExt;

         this.command = this.blenderPath
                 +Blender.SPACE
                 +Blender.PARAM_BG+Blender.SPACE+this.file
                 +Blender.SPACE
                 +Blender.PARAM_PATH+Blender.SPACE+this.path
                 +Blender.SPACE
                 +Blender.PARAM_FORMAT+Blender.SPACE+this.format
                 +Blender.SPACE
                 +Blender.PARAM_ADD_FILE_EXT+Blender.SPACE+this.addFileExt
                 +Blender.SPACE
                 +Blender.PARAM_START_FRAME+Blender.SPACE+this.startFrame
                 +Blender.SPACE
                 +Blender.PARAM_END_FRAME+Blender.SPACE+this.endFrame
                 +Blender.SPACE
                 +Blender.PARAM_ANIMATION;
    }

    public Blender(String blenderPath, String file, int startFrame,
            int endFrame, String path, String format, int addFileExt, Socket client) {
         this.blenderPath = blenderPath;
         this.file = file;
         this.startFrame = startFrame;
         this.endFrame = endFrame;
         this.path = path;
         this.format = format;
         this.addFileExt = addFileExt;

         this.command = this.blenderPath
                 +Blender.SPACE
                 +Blender.PARAM_BG+Blender.SPACE+this.file
                 +Blender.SPACE
                 +Blender.PARAM_PATH+Blender.SPACE+this.path
                 +Blender.SPACE
                 +Blender.PARAM_FORMAT+Blender.SPACE+this.format
                 +Blender.SPACE
                 +Blender.PARAM_ADD_FILE_EXT+Blender.SPACE+this.addFileExt
                 +Blender.SPACE
                 +Blender.PARAM_START_FRAME+Blender.SPACE+this.startFrame
                 +Blender.SPACE
                 +Blender.PARAM_END_FRAME+Blender.SPACE+this.endFrame
                 +Blender.SPACE
                 +Blender.PARAM_ANIMATION;

         this.client = client;
    }

    public void setBlenderPath(String blenderPath) {
        this.blenderPath = blenderPath;
    }

    public String getBlenderPath() {
        return this.blenderPath;
    }

    public void render() throws IOException, InterruptedException {
        boolean validCommand = true;

        if (this.blenderPath == null)
            validCommand = false;
        if (this.endFrame < this.startFrame) {
            this.endFrame = startFrame;
            System.out.println(
                    "WARNING! EndFrame is less than StartFrame!");
            System.out.println(
                    "WARNING! Setting EndFrame to equal of StartFrame");
        }
        if (this.file == null)
            validCommand = false;
        if (this.format == null)
            validCommand = false;
        if (this.path == null) {
            this.path = Blender.DEFAULT_PATH;
            System.out.println("WARNING! No output set!");
            System.out.println("WARNING! Setting output to \""
                    + Blender.DEFAULT_PATH +"\"");
        }

        if (validCommand) {
            try {
                Runtime run = Runtime.getRuntime();
                Process pr = run.exec(command);
                BufferedReader buf = new BufferedReader(new InputStreamReader(pr.getInputStream()));
                String line = buf.readLine();
                while (line != null) {
                    if (line.startsWith(Blender.MSG_APPEND_FRAME)) {
                        System.out.println(line);

                        int frame = 0;
                        {
                            String s = line.substring(Blender.MSG_APPEND_FRAME.length());
                            s = s.substring(0, s.indexOf(Blender.MSG_TIME));
                            s = s.replaceAll(" ", "");
                            frame = Integer.parseInt(s);
                        }

                        String sTime = line.substring(Blender.MSG_APPEND_FRAME.length() + 2);
                        sTime = sTime.substring(Blender.MSG_TIME.length());

                        getTimeLeft(frame, sTime);
                    }
                    line = buf.readLine();
                }

                pr.destroy();
                PrintWriter wr = new PrintWriter(this.client.getOutputStream());
                wr.write(Node.NODE_DONE);
            } catch (IOException ex) {
                Logger.getLogger(Blender.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }

    public void getTimeLeft(int currFrame, String sTime) throws IOException {
        PrintWriter wr = new PrintWriter(this.client.getOutputStream());
        double min = 0;
        double sec = 0;
        int ms  = 0;

        String[] times  = sTime.split(":");
        min = Double.parseDouble(times[0]);
        sec = Double.parseDouble(times[1].substring(0, 2));

        int lMin = 0;
        int lSec = 0;

        double m = (sec * (this.endFrame - currFrame)) / 60;
        if (m < 0.)
            lMin = 0;
        else
            lMin = (int) m;
        lSec = (int) ((m - lMin) * 60);

        System.out.println("Time left: " + lMin + "m:"+ lSec + "s");
        wr.write(Node.NODE_STATUS + "Time left: " + lMin + "m:"+ lSec + "s");

        double percentDone = ((double) currFrame / (double) this.endFrame) * 100;
        String sPercentDone = String.valueOf(percentDone);
        sPercentDone += "00";
        sPercentDone = sPercentDone.substring(0, sPercentDone.indexOf(".") + 3);
        System.out.println(sPercentDone + "% Done!");
        wr.write(Node.NODE_STATUS + sPercentDone + "% Done!");
    }

    public class Render implements Runnable {
        public void run() {
            
        }
    }
}
